Drag and Drop

Course- Android >

Android drag/drop framework permits your users to maneuver knowledge from one read to a different read within thecurrent layout employing a graphical drag and drop gesture. As of API eleven drag and drop of read onto different reads or view teams is supported.The framework includes following 3 vital elements to support drag & drop practicality −

  • Drag event class:

  • Drag listeners:

  • Helper methods and classes:

The Drag/Drop Process

There are basically four steps or states in the drag and drop process:

  • Started − This event occurs when you start dragging an item in a layout, your application calls startDrag() method to tell the system to start a drag. The arguments inside startDrag() method provide the data to be dragged, metadata for this data, and a callback for drawing the drag shadow.

    The framework initially reacts by getting back to back to your application to get a drag shadow. It at that point shows the drag shadow on the gadget. 

    Next, the framework sends a drag occasion with activity compose ACTION_DRAG_STARTED to the enlisted drag occasion audience members for all the View protests in the present format. 

    To keep on receiving drag occasions, including a conceivable drop occasion, a drag occasion audience must return genuine, If the drag occasion audience returns false, at that point it won't get drag occasions for the present operation until the point that the framework sends a drag occasion with activity compose ACTION_DRAG_ENDED.

  • Continuing − The client proceeds with the drag. Framework sends ACTION_DRAG_ENTERED activity took after by ACTION_DRAG_LOCATION activity to the enlisted drag occasion audience for the View where dragging point enters. The audience may modify its View protest's appearance because of the occasion or can respond by featuring its View. 

    The drag occasion audience gets an ACTION_DRAG_EXITED activity after the client has moved the drag shadow outside the jumping box of the View.

  • Dropped − The user releases the dragged item within the bounding box of a View. The system sends the View object's listener a drag event with action type ACTION_DROP.

  • Ended − Just after the action type ACTION_DROP, the system sends out a drag event with action type ACTION_DRAG_ENDED to indicate that the drag operation is over.

The DragEvent Class

The DragEvent represents an event that is sent out by the system at various times during a drag and drop operation. This class provides few Constants and important methods which we use during Drag/Drop process.

Constants

Following are all constants integers available as a part of DragEvent class.

Sr.No. Constants & Description
1 ACTION_DRAG_STARTED

Signals the start of a drag and drop operation.

2 ACTION_DRAG_ENTERED

Signals to a View that the drag point has entered the bounding box of the View.

3 ACTION_DRAG_LOCATION

Sent to a View after ACTION_DRAG_ENTERED if the drag shadow is still within the View object's bounding box.

4 ACTION_DRAG_EXITED

Signals that the user has moved the drag shadow outside the bounding box of the View.

5 ACTION_DROP

Signals to a View that the user has released the drag shadow, and the drag point is within the bounding box of the View.

6 ACTION_DRAG_ENDED

Signals to a View that the drag and drop operation has concluded.

Methods

Following are few important and most frequently used methods available as a part of DragEvent class.

Sr.No. Constants & Description
1 int getAction()

Inspect the action value of this event..

2 ClipData getClipData()

Returns the ClipData object sent to the system as part of the call to startDrag().

3 ClipDescription getClipDescription()

Returns the ClipDescription object contained in the ClipData.

4 boolean getResult()

Returns an indication of the result of the drag and drop operation.

5 float getX()

Gets the X coordinate of the drag point.

6 float getY()

Gets the Y coordinate of the drag point.

7 String toString()

Returns a string representation of this DragEvent object.

Listening for Drag Event

In the event that you need any of your perspectives inside a Layout ought to react Drag occasion then your view either executes View.OnDragListener or setup onDragEvent(DragEvent) callback technique. At the point when the framework calls the strategy or audience, it goes to them a DragEvent protest clarified previously. You can have both an audience and a callback technique for View protest. On the off chance that this happens, the framework first calls the audience and after that characterized callback as long as audience returns genuine. 

The blend of the onDragEvent(DragEvent) strategy and View.OnDragListener is practically equivalent to the mix of the onTouchEvent() and View.OnTouchListener utilized with touch occasions in old variants of Android. 

Starting a Drag Event 

You begin with making a ClipData and ClipData.Item for the information being moved. As a component of the ClipData protest, supply metadata that is put away in a ClipDescription question inside the ClipData. For a simplified operation that does not speak to information development, you might need to utilize invalid rather than a real protest. 

Next possibly you can stretch out stretch out View.DragShadowBuilder to make a drag shadow for dragging the view or basically you can utilize View.DragShadowBuilder(View) to make a default drag shadow that is an indistinguishable size from the View contention go to it, with the touch point focused in the drag shadow.

Example

Following example shows the functionality of a simple Drag & Drop using View.setOnLongClickListener(), View.setOnTouchListener()and View.OnDragEventListener().

Step Description
1 You will use Android studio IDE to create an Android application and name it as My Application under a package com.example.saira_000.myapplication. While creating this project, make sure you Target SDK and Compile With at the latest version of Android SDK to use higher levels of APIs.
2 Modify src/MainActivity.java file and add the code to define event listeners as well as a call back methods for the logo image used in the example.
3 Copy image abc.png in res/drawable-* folders. You can use images with different resolution in case you want to provide them for different devices.
4 Modify layout XML file res/layout/activity_main.xml to define default view of the logo images.
5 Run the application to launch Android emulator and verify the result of the changes done in the application.

Following is the content of the modified main activity file src/MainActivity.java. This file can include each of the fundamental lifecycle methods.


package com.example.saira_000.myapplication;

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.DragEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;


public class MainActivity extends Activity {
   ImageView img;
   String msg;
   private android.widget.RelativeLayout.LayoutParams layoutParams;
   
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      img=(ImageView)findViewById(R.id.imageView);
      
      img.setOnLongClickListener(new View.OnLongClickListener() {
         @Override
         public boolean onLongClick(View v) {
            ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());
            String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};
            
            ClipData dragData = new ClipData(v.getTag().toString(),mimeTypes, item);
            View.DragShadowBuilder myShadow = new View.DragShadowBuilder(img);
            
            v.startDrag(dragData,myShadow,null,0);
            return true;
         }
      });
      
      img.setOnDragListener(new View.OnDragListener() {
         @Override
         public boolean onDrag(View v, DragEvent event) {
            switch(event.getAction())
            {
               case DragEvent.ACTION_DRAG_STARTED:
               layoutParams = (RelativeLayout.LayoutParams)v.getLayoutParams();
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_STARTED");
               
               // Do nothing
               break;
               
               case DragEvent.ACTION_DRAG_ENTERED:
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_ENTERED");
               int x_cord = (int) event.getX();
               int y_cord = (int) event.getY();
               break;
               
               case DragEvent.ACTION_DRAG_EXITED :
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_EXITED");
               x_cord = (int) event.getX();
               y_cord = (int) event.getY();
               layoutParams.leftMargin = x_cord;
               layoutParams.topMargin = y_cord;
               v.setLayoutParams(layoutParams);
               break;
               
               case DragEvent.ACTION_DRAG_LOCATION  :
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_LOCATION");
               x_cord = (int) event.getX();
               y_cord = (int) event.getY();
               break;
               
               case DragEvent.ACTION_DRAG_ENDED   :
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_ENDED");
               
               // Do nothing
               break;
               
               case DragEvent.ACTION_DROP:
               Log.d(msg, "ACTION_DROP event");
               
               // Do nothing
               break;
               default: break;
            }
            return true;
         }
      });
      
      img.setOnTouchListener(new View.OnTouchListener() {
         @Override
         public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
               ClipData data = ClipData.newPlainText("", "");
               View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(img);
               
               img.startDrag(data, shadowBuilder, img, 0);
               img.setVisibility(View.INVISIBLE);
               return true;
            }
            else
            {
               return false;
            }
         }
      });
   }
   
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.menu_main, menu);
      return true;
   }
   
   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      
      int id = item.getItemId();
      
      //noinspection SimplifiableIfStatement
      if (id == R.id.action_settings) {
         return true;
      }
      return super.onOptionsItemSelected(item);
   }
}

Following will be the content of res/layout/activity_main.xml file −


 xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools" 
   android:layout_width="match_parent"
   android:layout_height="match_parent" 
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   android:paddingBottom="@dimen/activity_vertical_margin" 
   tools:context=".MainActivity">
   
   
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Drag and Drop Example"
      android:id="@+id/textView"
      android:layout_alignParentTop="true"
      android:layout_centerHorizontal="true"
      android:textSize="30dp" />
      
   
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Tutorials Point"
      android:id="@+id/textView2"
      android:layout_below="@+id/textView"
      android:layout_centerHorizontal="true"
      android:textSize="30dp"
      android:textColor="#ff14be3c" />>
      
   
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/imageView"
      android:src="@drawable/abc"
      android:layout_below="@+id/textView2"
      android:layout_alignRight="@+id/textView2"
      android:layout_alignEnd="@+id/textView2"
      android:layout_alignLeft="@+id/textView2"
      android:layout_alignStart="@+id/textView2" />

Following will be the content of res/values/strings.xml to define two new constants −


xml version="1.0" encoding="utf-8"?>

    name="app_name">My Application
    name="action_settings">Settings

Following is the default content of AndroidManifest.xml


xml version="1.0" encoding="utf-8"?>
 xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.guidemo"
   android:versionCode="1"
   android:versionName="1.0" >
   
   
      android:minSdkVersion="11"
      android:targetSdkVersion="22" />
      
   
      android:allowBackup="true"
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme" >
      
      
         android:name="com.example.guidemo.MainActivity"
         android:label="@string/app_name" >
      
         
             android:name="android.intent.action.MAIN" />
             android:name="android.intent.category.LAUNCHER" />
         
      
      
      
   

Let's try to run your My Application application. I assume you had created your AVD while doing environment setup. To run the app from Android Studio, open one of your project's activity files and click Run  icon from the toolbar. Android studio installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display

Now do long click on the displayed TutorialsPoint logo and you will see that logo image moves a little after 1 seconds long click from its place, its the time when you should start dragging the image. You can drag it around the screen and drop it at a new location.